#!/usr/bin/env node

const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');

// 颜色输出
const colors = {
  reset: '\x1b[0m',
  bright: '\x1b[1m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  magenta: '\x1b[35m',
  cyan: '\x1b[36m',
};

function colorLog(color, message) {
  console.log(`${colors[color]}${message}${colors.reset}`);
}

function runCommand(command, args, options = {}) {
  return new Promise((resolve, reject) => {
    const child = spawn(command, args, {
      stdio: 'inherit',
      shell: true,
      ...options,
    });

    child.on('close', (code) => {
      if (code === 0) {
        resolve();
      } else {
        reject(new Error(`Command failed with exit code ${code}`));
      }
    });

    child.on('error', reject);
  });
}

async function runTests() {
  const args = process.argv.slice(2);
  const testType = args[0] || 'all';
  const coverage = args.includes('--coverage');
  const watch = args.includes('--watch');

  colorLog('cyan', '🧪 Running Tauri Modern Template Tests');
  console.log('');

  try {
    switch (testType) {
      case 'frontend':
      case 'front':
        await runFrontendTests(coverage, watch);
        break;
      
      case 'backend':
      case 'back':
      case 'rust':
        await runBackendTests(coverage);
        break;
      
      case 'e2e':
        await runE2ETests();
        break;
      
      case 'all':
      default:
        await runAllTests(coverage);
        break;
    }

    colorLog('green', '✅ All tests completed successfully!');
  } catch (error) {
    colorLog('red', `❌ Tests failed: ${error.message}`);
    process.exit(1);
  }
}

async function runFrontendTests(coverage = false, watch = false) {
  colorLog('blue', '📱 Running Frontend Tests...');
  
  const args = ['test'];
  
  if (coverage) {
    args.push('--coverage');
  }
  
  if (watch) {
    args.push('--watch');
  }

  await runCommand('npm', args);
  colorLog('green', '✅ Frontend tests completed');
}

async function runBackendTests(coverage = false) {
  colorLog('blue', '🦀 Running Rust Backend Tests...');
  
  const args = ['test'];
  
  if (coverage) {
    // 使用 cargo-tarpaulin 进行覆盖率测试
    try {
      await runCommand('cargo', ['tarpaulin', '--out', 'Html', '--output-dir', 'coverage'], {
        cwd: path.join(process.cwd(), 'src-tauri'),
      });
      colorLog('green', '📊 Coverage report generated in src-tauri/coverage/');
    } catch (error) {
      colorLog('yellow', '⚠️  cargo-tarpaulin not found, running tests without coverage');
      await runCommand('cargo', args, {
        cwd: path.join(process.cwd(), 'src-tauri'),
      });
    }
  } else {
    await runCommand('cargo', args, {
      cwd: path.join(process.cwd(), 'src-tauri'),
    });
  }
  
  colorLog('green', '✅ Backend tests completed');
}

async function runE2ETests() {
  colorLog('blue', '🎭 Running E2E Tests...');
  
  // 检查是否有 Playwright 配置
  if (fs.existsSync('playwright.config.ts')) {
    await runCommand('npx', ['playwright', 'test']);
  } else {
    colorLog('yellow', '⚠️  No Playwright configuration found, skipping E2E tests');
  }
  
  colorLog('green', '✅ E2E tests completed');
}

async function runAllTests(coverage = false) {
  colorLog('bright', '🚀 Running All Tests...');
  console.log('');
  
  // 运行前端测试
  await runFrontendTests(coverage);
  console.log('');
  
  // 运行后端测试
  await runBackendTests(coverage);
  console.log('');
  
  // 运行 E2E 测试
  await runE2ETests();
  console.log('');
}

// 显示帮助信息
function showHelp() {
  console.log(`
${colors.bright}Tauri Modern Template Test Runner${colors.reset}

${colors.cyan}Usage:${colors.reset}
  npm run test [type] [options]

${colors.cyan}Test Types:${colors.reset}
  all        Run all tests (default)
  frontend   Run only frontend tests
  backend    Run only backend/Rust tests
  e2e        Run only E2E tests

${colors.cyan}Options:${colors.reset}
  --coverage Generate coverage reports
  --watch    Watch mode for frontend tests
  --help     Show this help message

${colors.cyan}Examples:${colors.reset}
  npm run test                    # Run all tests
  npm run test frontend           # Run only frontend tests
  npm run test backend --coverage # Run backend tests with coverage
  npm run test frontend --watch   # Run frontend tests in watch mode
  npm run test e2e                # Run only E2E tests
`);
}

// 主函数
if (require.main === module) {
  if (process.argv.includes('--help') || process.argv.includes('-h')) {
    showHelp();
    process.exit(0);
  }
  
  runTests().catch((error) => {
    colorLog('red', `❌ Test runner failed: ${error.message}`);
    process.exit(1);
  });
}

module.exports = {
  runTests,
  runFrontendTests,
  runBackendTests,
  runE2ETests,
};
